//声明构造函数
function Promise(executor) {
  //状态属性
  this.PromiseState = "pending";
  //结果值属性
  this.PromiseResult = undefined;
  //
  this.callbacks = []; // {}
  //resolve 函数
  //更改 promise 实例对象状态为成功, 设置成功的结果值
  let success = (value) => {
    //判断状态是否为 pending
    if (this.PromiseState !== "pending") return;
    //更改 promise 实例对象状态为成功
    this.PromiseState = "fulfilled";
    //设置成功的结果值
    this.PromiseResult = value;
    //状态改变之后, 执行对应的回调
    if (this.callbacks.length > 0) {
      //执行成功的回调
      this.callbacks.forEach((cb) => {
        //执行成功的回调
        cb.ok(this.PromiseResult);
      });
    }
  };

  //reject 函数
  let fail = (reason) => {
    //判断状态是否为 pending
    if (this.PromiseState !== "pending") return;
    //更改 promise 实例对象状态为失败
    this.PromiseState = "rejected";
    //设置成功的结果值
    this.PromiseResult = reason;
    //状态改变之后, 执行对应的回调
    if (this.callbacks.length > 0) {
      //执行失败的回调
      this.callbacks.forEach((cb) => {
        //执行失败的回调
        cb.ng(this.PromiseResult);
      });
    }
  };

  try {
    //执行器函数是一个同步回调
    executor(success, fail);
  } catch (e) {
    //更改 promise 实例对象状态为失败
    fail(e);
  }
}

//原型声明 then 方法
Promise.prototype.then = function (onFulfilled, onRejected) {
  //为 onRejected 设置默认值
  if (typeof onRejected !== "function") {
    onRejected = (reason) => {
      throw reason;
    };
  }

  //判断成功的回调
  if (typeof onFulfilled !== "function") {
    onFulfilled = (value) => value;
  }

  //返回一个新的 promise 对象
  return new Promise((resolve, reject) => {
    //callback()
    //声明函数 封装重复代码
    let callback = (type) => {
      try {
        //获取回调函数的返回值
        let res = type(this.PromiseResult);
        //判断
        if (res instanceof Promise) {
          res.then(
            (v) => {
              resolve(v);
            },
            (r) => {
              reject(r);
            }
          );
        } else {
          resolve(res);
        }
      } catch (e) {
        reject(e);
      }
    };
    //判断
    if (this.PromiseState === "fulfilled") {
      setTimeout(() => {
        callback(onFulfilled);
      });
    }

    //失败的情况
    if (this.PromiseState === "rejected") {
      setTimeout(() => {
        callback(onRejected);
      })
    }

    //处理 pending 情况
    if (this.PromiseState === "pending") {
      //保存回调
      this.callbacks.push({
        ok: () => callback(onFulfilled),
        ng: () => callback(onRejected),
      });
    }
  });
};

//声明 catch 方法
Promise.prototype.catch = function (onRejected) {
  return this.then(undefined, onRejected);
};

//添加 resolve 方法
Promise.resolve = function (value) {
  return new Promise((resolve, reject) => {
    //判断
    if (value instanceof Promise) {
      value.then(
        (v) => {
          resolve(v);
        },
        (r) => {
          reject(r);
        }
      );
    } else {
      //不是 promise
      resolve(value);
    }
  });
};

//添加 reject 方法
Promise.reject = function (reason) {
  return new Promise((resolve, reject) => {
    reject(reason);
  });
};

//声明 all 方法
Promise.all = function (promiseArr) {
  //声明一个数组
  let resultArr = [];
  let counter = 0;
  //返回一个新的 promise    [undefined, 'Yes', 'Yeah']
  return new Promise((resolve, reject) => {
    //遍历promise数组
    promiseArr.forEach((p, index) => {
      //调用 then 方法
      p.then(
        (v) => {
          //当数组中所有的 promise 都为成功的时候, 调用 resolve
          // resultArr.push(v); //使用 push 有顺序问题
          resultArr[index] = v;
          //计数变量加 1
          counter++;
          //判断
          if (counter === promiseArr.length) {
            //表明所有都成功
            resolve(resultArr);
          }
        },
        (r) => {
          reject(r);
        }
      );
    });
  });
};

//声明 race 方法
Promise.race = function (promiseArr) {
  //返回新的 promise 对象
  return new Promise((resolve, reject) => {
    //遍历 promiseArr 数组
    promiseArr.forEach((item) => {
      item.then(
        (v) => {
          resolve(v);
        },
        (r) => {
          reject(r);
        }
      );
    });
  });
};
